package cn.gailvlun.gll.presentation.main

import android.arch.lifecycle.ViewModel
import cn.gailvlun.gll.chatlib.bean.SystemNotification
import cn.gailvlun.gll.chatlib.db.ChatDB2
import cn.gailvlun.gll.chatlib.dialog.Dialog
import cn.gailvlun.gll.chatlib.message.Message
import cn.gailvlun.gll.net.Member
import cn.gailvlun.gll.net.apartment.room.Room
import cn.gailvlun.gll.net.base.Profile
import cn.gailvlun.gll.net.base.friend.FriendNotification
import cn.gailvlun.gll.util.LogUtil
import cn.gailvlun.gll.util.ProfileUtil
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.rxkotlin.Flowables
import io.realm.Realm
import io.realm.RealmResults
import io.realm.Sort
import java.util.*
import java.util.concurrent.TimeUnit



class DialogListViewModel : ViewModel {

    var realm: Realm?

    private val systemNotiResults: RealmResults<SystemNotification>
    private val friendNotiResults: RealmResults<FriendNotification>
    private val dialogRealmResults: RealmResults<Dialog>

    val dialogObservable: Flowable<Triple<RealmResults<SystemNotification>,
            RealmResults<FriendNotification>, RealmResults<Dialog>>>

    private val disposable: Disposable

    constructor() {
        LogUtil.d("create: dialogListViewModel: $this")

        this.realm = Realm.getInstance(ChatDB2.getConfiguration())

        
        disposable = realm!!.where(Message::class.java)
                .distinct("dialogId")
                .sort("created", Sort.DESCENDING)
                .findAllAsync()
                .asFlowable()
                .filter { it.isLoaded }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { realmResults ->
                    realm!!.beginTransaction()
                    for (message in realmResults) {
                        var dialog = searchDialog(message.dialogId)
                        if (dialog == null) {
                            dialog = Dialog()
                            dialog.id = message.dialogId
                            if (message.isRoom) {
                                dialog.room = searchRoom(message.userOrRoomId)
                            } else {
                                dialog.profile = searchUserProfile(message.userOrRoomId)
                            }
                            if (dialog.profile != null || dialog.room != null) {
                                dialog.unreadCount = searchUnreadCount(message.dialogId)
                                dialog.message = message
                                realm!!.insertOrUpdate(dialog)
                            }
                        } else {
                            if (dialog.profile != null || dialog.room != null) {
                                dialog.unreadCount = searchUnreadCount(message.dialogId)
                                dialog.message = message
                                realm!!.insertOrUpdate(dialog)
                            }
                        }
                    }
                    
                    realm!!.where(Dialog::class.java)
                            .isNull("message")
                            .findAll()
                            .deleteAllFromRealm()
                    realm!!.commitTransaction()
                }

        systemNotiResults = realm!!.where(SystemNotification::class.java)


                .sort("created", Sort.DESCENDING)
                .findAllAsync()

        friendNotiResults = realm!!.where(FriendNotification::class.java)
                .sort("created", Sort.DESCENDING)
                .findAllAsync()

        dialogRealmResults = realm!!.where(Dialog::class.java)
                .sort("message.created", Sort.DESCENDING)
                .findAllAsync()

        dialogObservable = Flowables.combineLatest(systemNotiResults.asFlowable().filter { it.isLoaded },
                friendNotiResults.asFlowable().filter { it.isLoaded },
                dialogRealmResults.asFlowable().filter { it.isLoaded })
                .sample(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
    }

    private fun searchDialog(dialogId: String): Dialog? {
        return realm!!.where(Dialog::class.java)
                .equalTo("id", dialogId)
                .findFirst()
    }

    private fun searchRoom(roomId: Int): Room? {
        return realm!!.where(Room::class.java)
                .equalTo("id", roomId)
                .findFirst()
    }

    private fun searchUserProfile(userId: Int): Profile? {
        return realm!!.where(Profile::class.java)
                .equalTo("id", userId)
                .findFirst()
    }

    private fun searchUnreadCount(dialogId: String): Long {
        return realm!!.where(Message::class.java)
                .equalTo("dialogId", dialogId)
                .equalTo("unread", true)
                .count()
    }

    fun isHaveMember(roomId: Int): Boolean {
        return realm!!.where(Member::class.java)
                .equalTo("room", roomId)
                .equalTo("owner.id", ProfileUtil.getUserId())
                .findFirst() != null
    }

    fun saveMyMember(member: Member) {
        realm!!.executeTransaction { realm ->
            realm.insertOrUpdate(member)
        }
    }

    fun testAddMessage() {
        for (i in 0..10) {
            val msg = Message.text("123", Date(), ProfileUtil.getProfile(), "user:62")
            realm!!.executeTransaction { realm ->
                realm.insertOrUpdate(msg)
            }
        }
    }

    override fun onCleared() {
        disposable.dispose()
        realm?.close()
        realm = null

        LogUtil.d("dialogListViewModel $this onCleared")
        super.onCleared()
    }
}
